package com.xu.ai.model.openai.controller;

import java.util.List;
import java.util.Map;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.AssistantPromptTemplate;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import reactor.core.publisher.Flux;

import com.xu.ai.model.openai.enums.ChatModelEnum;
import com.xu.ai.model.openai.pojo.ActorFilms;

/**
 * 聊天客户端controller
 *
 * @author xuguan
 * @since 2025/9/15
 */
@RestController
@RequestMapping("/api/chat")
public class ChatClientController {
	@Autowired
	private ChatClient chatClient;
	@Autowired
	private ChatMemory chatMemory;
	@Autowired
	private VectorStore vectorStore;

	@GetMapping(path = "/call/content")
	String callContent(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
				.user(userInput)
				.call()
				.content();
	}

	@GetMapping(path = "/call/chat-response")
	ChatResponse callChatResponse(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
				.user(userInput)
				.call()
				.chatResponse();
	}

	@GetMapping(path = "/call/entity")
	ActorFilms callEntity(@RequestParam(value = "actorName", defaultValue = "成龙") String actorName) {
		String template = """
				请介绍演员{actorName}三部最有名的电影作品.
				""";
		final AssistantPromptTemplate apt = new AssistantPromptTemplate(template);
		final Prompt prompt = apt.create(Map.of("actorName", actorName));
		return this.chatClient.prompt(prompt)
				.call()
				.entity(ActorFilms.class);
	}

	@GetMapping(path = "/stream/content", produces = "text/html;charset=UTF-8")
	Flux<String> streamContent(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
				.user(userInput)
				.stream()
				.content();
	}

	@GetMapping(path = "/stream/chat-response", produces = "text/html;charset=UTF-8")
	Flux<ChatResponse> streamChatResponse(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
				.user(userInput)
				.stream()
				.chatResponse();
	}

	@GetMapping(path = "/stream/multi-model", produces = "text/html;charset=UTF-8")
	Flux<String> streamMultiModel(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput,
								  @RequestParam(value = "model", defaultValue = "qwen-plus-latest") String model) {
		if (!StringUtils.hasText(model)) {
			model = ChatModelEnum.QWEN_MAX.getName();
		} else {
			boolean exist = false;
			for (ChatModelEnum item : ChatModelEnum.values()) {
				if (item.getName().equals(model)) {
					exist = true;
					break;
				}
			}
			if (!exist) {
				return Flux.just("暂不支持该模型");
			}
		}
		final OpenAiChatOptions options = OpenAiChatOptions.builder()
				.model(model)
				.build();
		return this.chatClient.prompt()
				.options(options)
				.user(userInput)
				.stream()
				.content();
	}

	@GetMapping(path = "/stream/memory", produces = "text/html;charset=UTF-8")
	Flux<String> memoryGenerateStream(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput,
									  @RequestParam(value = "chatId", defaultValue = "1") String chatId) {
		return this.chatClient.prompt()
				.user(userInput)
				.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
				.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
				.stream()
				.content();
	}

	@GetMapping(path = "/stream/prompt", produces = "text/html;charset=UTF-8")
	Flux<String> streamPrompt(@RequestParam(value = "name", defaultValue = "xu-ai智能助手") String name,
							  @RequestParam(value = "voice", defaultValue = "幽默") String voice) {
		String userText = """
				告诉我海盗黄金时代的三位著名海盗以及他们这样做的原因。
				至少为每个海盗写一句话。
				""";
		Message userMessage = new UserMessage(userText);

		String systemText = """
				您是一个有用的人工智能助手，可以帮助人们查找信息。
				你的名字是 {name},
				您应该使用你的姓名并以 {voice} 的风格回复用户的请求。
				""";
		SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
		Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));

		Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

		return this.chatClient.prompt(prompt)
				.user(userText)
				.stream()
				.content();
	}

	@GetMapping(path = "/stream/rag", produces = "text/html;charset=UTF-8")
	Flux<String> streamRag(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
				.user(userInput)
				.advisors(QuestionAnswerAdvisor.builder(vectorStore).build())
				.stream()
				.content();
	}
}
